package udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

// socket 对象就是(网卡对象)文件对象 操作系统中 一切都是文件
public class UdpEchoServer {
    // 对于一个服务器来说，核心流程也要分为两步
    // 1. 进行初始化操作 (实例化 Socket 对象 )
    // 2. 进入主循环，接受并处理请求 ;
    //  a) 请求数据并解析;
    //  b) 根据亲求计算响应
    //  c) 把响应结果返回到客户端
    private DatagramSocket socket = null;

    public UdpEchoServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
        while(true){
            // a) 接受请求并解析
            // DatagramPacket 对象包含了他将被发送过去的主机的IP 地址 和端口号
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);

            // 当客户端的数据过来后，此时receive 就会把收到的数据放到DatagramSocket 对象的缓冲区域中
            socket.receive(requestPacket); // 只要没有数据发送 一直处于 阻塞状态
            String request = new String(requestPacket.getData(),0,requestPacket.getLength()).trim();// trim 方法可以干掉不必要的空白字符
            // b) 根据请求计算响应
            String response = process(request);

            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),request.getBytes().length,
                               /*这个包 发给谁 （目的的ip 和端口号 : 这两个信息就包含在requestPacket 内部） */  requestPacket.getSocketAddress());
            socket.send(responsePacket);
            System.out.printf("[%s:%d] request : %s; response : %s \n",requestPacket.getAddress().toString(),
                    requestPacket.getPort(),request,response);
        }
    }


    protected String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer udpEchoServer = new UdpEchoServer(9090);
        udpEchoServer.start();
    }
}


//
// 用这种语法 可以在程序结束时自动关闭资源
//    try(指定资源 eg: InputStream  ins = new InputStream())//可指定多个资源
//        {
//          // 对资源操作
//        }
// 相当于
//    try{
//        // 打开 资源 A
//    }finally{
    //        try{
    //            //关闭资源A
    //            }
//            }
//